package top.happylaishop.shop.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import top.happylaishop.shop.common.Const;
import top.happylaishop.shop.dao.UserDao;
import top.happylaishop.shop.dto.CurrentUserDto;
import top.happylaishop.shop.dto.UserDto;
import top.happylaishop.shop.pojo.User;
import top.happylaishop.shop.service.UserService;
import top.happylaishop.shop.utils.BeanValidator;
import top.happylaishop.shop.utils.CommonUtils;
import top.happylaishop.shop.utils.resp.BaseResponse;
import top.happylaishop.shop.utils.resp.RestResponse;

import java.util.Date;
import java.util.Map;

@Service
public class UserServiceImpl implements UserService {

    @Value("${web.session.timeout}")
    private long sessionTimeout;
    @Autowired
    private UserDao userDao;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public RestResponse<CurrentUserDto> login(UserDto userDto) {
        LambdaQueryWrapper<User> lambdQueryWrapper = new LambdaQueryWrapper<>();
        lambdQueryWrapper.eq(User::getUsername, userDto.getUsername())
                .eq(User::getPassword, userDto.getPassword());
        User user = userDao.selectOne(lambdQueryWrapper);
        if(user == null){
            return RestResponse.failed("用户名或者密码错误");
        }
        user.setPassword(Const.BLANK);
        CurrentUserDto currentUserDto = new CurrentUserDto();
        currentUserDto.setUserDto(BeanUtil.copyProperties(user, UserDto.class));
        currentUserDto.setLoginTime(System.currentTimeMillis());
        currentUserDto.setToken(IdUtil.simpleUUID());
        stringRedisTemplate.opsForValue().set(CommonUtils.generateLoginToken(currentUserDto.getToken()), JSON.toJSONString(currentUserDto), sessionTimeout);
        return RestResponse.defaultSucessData(currentUserDto);
    }

    @Override
    public BaseResponse register(UserDto userDto) {
        Map<String, String> errors = BeanValidator.validateForObjects(userDto);
        if(errors != null && errors.size() > 0){
            return BaseResponse.failed(JSON.toJSONString(errors));
        }
        BaseResponse baseResponse = checkValid(userDto.getUsername(), Const.USERNAME);
        if(!baseResponse.isSuccess()){
            return baseResponse;
        }
        User user = BeanUtil.copyProperties(userDto, User.class);
        user.setStatus(Const.AccountStatusEnum.USING.getCode());
        user.setCreateTime(new Date());
        user.setUpdateTime(user.getCreateTime());
        user.setCreateUserId(0);
        user.setUpdateUserId(0);
        int count = userDao.insert(user);
        if(count <= 0){
            return BaseResponse.FAIL;
        }
        return BaseResponse.success();
    }

    @Override
    public BaseResponse checkValid(String str, String type) {
        if(StrUtil.isNotBlank(str)){
            LambdaQueryWrapper<User> lambdQueryWrapper = new LambdaQueryWrapper<>();
            String errMsg = null;
            if(StrUtil.equals(type, Const.USERNAME)){
                lambdQueryWrapper.eq(User::getUsername, str);
                errMsg = Const.ERROR_MSG_USERNAME_EXISTS;
            } else if(StrUtil.equals(type, Const.EMAIL)){
                lambdQueryWrapper.eq(User::getEmail, str);
                errMsg = Const.ERROR_MSG_EMAIL_EXISTS;
            }
            Integer count = userDao.selectCount(lambdQueryWrapper);
            if(count > 0){
                return BaseResponse.failed(errMsg);
            }
        }
        return BaseResponse.OK;
    }

    @Override
    public BaseResponse checkAnswer(String username, String question, String answer) {
        User user = getByUsername(username);
        if(user.getQuestion().equals(question) && user.getAnswer().equals(answer)){
            return RestResponse.success();
        }
        return BaseResponse.failed("问题的答案错误");
    }

    @Override
    public RestResponse<UserDto> updateInformation(UserDto userDto) {
        User user = new User();
        user.setId(userDto.getId());
        user.setUpdateTime(new Date());
        user.setUpdateUserId(userDto.getId());
        user.setEmail(userDto.getEmail());
        user.setQuestion(userDto.getQuestion());
        user.setAnswer(userDto.getAnswer());
        userDao.updateById(user);
        return RestResponse.defaultSucessData(userDao.selectById(user.getId()));
    }

    @Override
    public BaseResponse resetPassword(String passwordOld, String passwordNew, UserDto currentUser) {
        if(StrUtil.isNotBlank(passwordNew) || StrUtil.isBlank(passwordOld)){
            return BaseResponse.failed(Const.ERROR_MSG_PASSWORD_NOTBLANK);
        }
        User userDb = userDao.selectById(currentUser.getId());
        if(userDb.getPassword().equals(passwordOld)){
            return BaseResponse.failed(Const.ERROR_MSG_PASSWORD_NOTCORRECT);
        }
        User user = new User();
        user.setId(currentUser.getId());
        user.setPassword(passwordNew);
        user.setUpdateTime(new Date());
        user.setUpdateUserId(user.getId());
        userDao.updateById(user);
        return BaseResponse.success();
    }

    @Override
    public BaseResponse forgetRestPassword(String username, String passwordNew) {
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(User::getUsername, username)
                .eq(User::getStatus, Const.AccountStatusEnum.USING.getCode());
        User user = new User();
        user.setPassword(passwordNew);
        user.setUpdateTime(new Date());
        user.setUpdateUserId(user.getId());
        userDao.update(user, updateWrapper);
        return BaseResponse.success();
    }

    @Override
    public String getQuestionByUsername(String username) {
        User user = getByUsername(username);
        return user == null ? "" : user.getQuestion();
    }

    @Override
    public User getByUsername(String username) {
        LambdaQueryWrapper<User> lambdQueryWrapper = new LambdaQueryWrapper<>();
        lambdQueryWrapper.eq(User::getUsername, username);
        return userDao.selectOne(lambdQueryWrapper);
    }
}
